#include <iostream>
#include <pthread.h>
#include <string>
#include <cstring>
#include <vector>
#include <unistd.h>
#include "LockGuard.hpp"
using namespace std;
#define NUM 3
int ticket = 1000;
// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
// class pthreadData
// {
// public:
//     pthreadData(int number)
//     {
//         pthreadname = "thread-" + to_string(number);
//     }

// public:
//     string pthreadname;
// };
// void *getTicket(void *args)
// {
//     pthreadData *td = static_cast<pthreadData *>(args);
//     const char *name = td->pthreadname.c_str();

//     int cnt = 10;
//     while (true)
//     {
//         // pthread_mutex_lock(&lock);
//         if (ticket > 0)
//         {
//             usleep(1000);
//             printf("%s get a ticket:%d\n", name, ticket);
//             ticket--;
//             // pthread_mutex_unlock(&lock);
//         }
//         else
//         {
//             // pthread_mutex_unlock(&lock);
//             break;
//         }
//         usleep(13);
//     }
//     printf("%s,quit...\n", name);
//     return nullptr;
// }
// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
class pthreadData
{
public:
    pthreadData(int number, pthread_mutex_t *mutex)
    {
        pthreadname = "thread-" + to_string(number);
        lock = mutex;
    }

public:
    string pthreadname;
    pthread_mutex_t *lock;
};
void *getTicket(void *args)
{
    pthreadData *td = static_cast<pthreadData *>(args);
    const char *name = td->pthreadname.c_str();

    int cnt = 10;
    while (true)
    {
        {
            LockGuard lockguard(td->lock);
            if (ticket > 0)
            {
                usleep(1000);
                printf("%s get a ticket:%d\n", name, ticket);
                ticket--;
            }
            else
                break;
        }
        usleep(13);
    }
    printf("%s,quit...\n", name);
    return nullptr;
}
int main()
{
    pthread_mutex_t lock;
    pthread_mutex_init(&lock, nullptr);
    vector<pthread_t> tids;
    vector<pthreadData *> pthread_datas;
    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        pthreadData *td = new pthreadData(i, &lock);
        pthread_datas.push_back(td);
        pthread_create(&tid, nullptr, getTicket, pthread_datas[i - 1]);
        tids.push_back(tid);
    }
    for (auto tid : tids)
    {
        pthread_join(tid, nullptr);
    }
    for (auto pthread : pthread_datas)
    {
        delete pthread;
    }
    pthread_mutex_destroy(&lock);

    return 0;
}
// class pthreadData
// {
// public:
//     pthreadData(int number, pthread_mutex_t *mutex)
//     {
//         pthreadname = "thread-" + to_string(number);
//         lock = mutex;
//     }

// public:
//     string pthreadname;
//     pthread_mutex_t *lock;
// };
// void *getTicket(void *args)
// {
//     pthreadData *td = static_cast<pthreadData *>(args);
//     const char *name = td->pthreadname.c_str();

//     int cnt = 10;
//     while (true)
//     {
//         pthread_mutex_lock(td->lock);
//         if (ticket > 0)
//         {
//             usleep(1000);
//             printf("%s get a ticket:%d\n", name, ticket);
//             ticket--;
//             pthread_mutex_unlock(td->lock);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->lock);
//             break;
//         }
//         usleep(13);
//     }
//     printf("%s,quit...\n", name);
//     return nullptr;
// }
// int main()
// {
//     pthread_mutex_t lock;
//     pthread_mutex_init(&lock, nullptr);
//     vector<pthread_t> tids;
//     vector<pthreadData *> pthread_datas;
//     for (int i = 1; i <= NUM; i++)
//     {
//         pthread_t tid;
//         pthreadData *td = new pthreadData(i, &lock);
//         pthread_datas.push_back(td);
//         pthread_create(&tid, nullptr, getTicket, pthread_datas[i - 1]);
//         tids.push_back(tid);
//     }
//     for (auto tid : tids)
//     {
//         pthread_join(tid, nullptr);
//     }
//     for (auto pthread : pthread_datas)
//     {
//         delete pthread;
//     }
//     pthread_mutex_destroy(&lock);

//     return 0;
// }